/*
 * Test program for 8x8 LED matrix (single color) and two shift registor
 * 74HC595 
 *
 * HISTORY
 * 2010/9/24 new 
 */

/*
 * Copyright (c) 2010 elekid
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

#include <Metro.h>


// for 7 segments x 4 display

/* OLD CONFIG
int CLOCK_PIN_A =4;
int DATA_PIN_A  =5;

int CLOCK_PIN_K =2;
int DATA_PIN_K  =3;
int LATCH_PIN_K =6;
*/


/* NEW CONFIG */
int CLOCK_PIN_K =6;
int DATA_PIN_K  =7;
int LATCH_PIN_K =8;

int CLOCK_PIN_A =4;
int DATA_PIN_A  =5;

#define SWITCH_ROW_COUNT 100  // loop() count
#define UPDATE_MATRIX_PERIOD 60  // msec

int ptn_cnts[4] = {4,12,20,28};


int ptn[64][2] = 
{
// total 4
  {3,3},
  {3,4},
  {4,4},
  {4,3},
  // total 12
  {2,2},
  {2,3},
  {2,4},
  {2,5},
  {3,5},
  {4,5},
  {5,5},
  {5,4},
  {5,3},
  {5,2},
  {4,2},
  {3,2},
  // total 20
  {1,1},
  {1,2},
  {1,3},
  {1,4},
  {1,5},
  {1,6},
  {2,6},
  {3,6},
  {4,6},
  {5,6},
  {6,6},
  {6,5},
  {6,4},
  {6,3},
  {6,2},
  {6,1},
  {5,1},
  {4,1},
  {3,1},
  {2,1},
  // total 28
  {0,0},
  {0,1},
  {0,2},
  {0,3},
  {0,4},
  {0,5},
  {0,6},
  {0,7},
  {1,7},
  {2,7},
  {3,7},
  {4,7},
  {5,7},
  {6,7},
  {7,7},
  {7,6},
  {7,5},
  {7,4},
  {7,3},
  {7,2},
  {7,1},
  {7,0},
  {6,0},
  {5,0},
  {4,0},
  {3,0},
  {2,0},
  {1,0}
};





byte Matrix[8] = {
B11111111,
B11111111,
B11111111,
B11111111,
B11111111,
B11111111,
B11111111,
B11111111 };

unsigned long switchRowCounter=SWITCH_ROW_COUNT;
Metro updateMatrixTimer = Metro(UPDATE_MATRIX_PERIOD);



void setup()
{
  Serial.begin(9600);
  
  pinMode(LATCH_PIN_K, OUTPUT);  // HC595
  pinMode(CLOCK_PIN_K, OUTPUT);
  pinMode(CLOCK_PIN_A, OUTPUT);
  pinMode(DATA_PIN_K,  OUTPUT);
  pinMode(DATA_PIN_A,  OUTPUT);

}
void loop()
{ 

   displayMatrix();
   
  if ( updateMatrixTimer.check() == 1 ) {
    plotData();
  }


}    


void displayMatrix() 
{
  static int cnt=0;

  if (++switchRowCounter < SWITCH_ROW_COUNT ) {
    return;
  }

  switchRowCounter=0;

  digitalWrite(LATCH_PIN_K , LOW);     // HC595
  shiftOut(DATA_PIN_K, CLOCK_PIN_K, MSBFIRST, 0xFF);
  digitalWrite(LATCH_PIN_K , HIGH);    // HC595
  
  // one bit shift for shift registor #1
  if (cnt == 0 ) {
    digitalWrite(DATA_PIN_A, HIGH);
  } else {
    digitalWrite(DATA_PIN_A, LOW);
  }
  digitalWrite(CLOCK_PIN_A, HIGH);
  digitalWrite(CLOCK_PIN_A, LOW);

  // eight bits shift for shift registor #2
  digitalWrite(LATCH_PIN_K , LOW);      // HC595
  shiftOut(DATA_PIN_K, CLOCK_PIN_K, MSBFIRST, Matrix[cnt]);
  digitalWrite(LATCH_PIN_K , HIGH);     // HC595

  if (++cnt >= 8 ) {
    cnt=0;
  }
}

void plotData() {

  static int pt=99;
  static int c_pt=99;
  static int ptn_num=99;
  static int max_pt =0;

  if (c_pt >= max_pt ) {
    for (int i=0; i<8 ; i++) {
      Matrix[i]=0xFF;
    }
    ptn_num++;
    if (ptn_num >= 4 ) {
      ptn_num = 0 ;
      pt=0;
    }
    max_pt =ptn_cnts[ptn_num];
    c_pt=0;
  }

  int row = ptn[pt][0];
  int col = ptn[pt][1];
  Matrix[row] = Matrix[row] ^ (1 << col ); // XOR
  
  Serial.print(row);
  Serial.print(",");
  Serial.print(col);
  Serial.println(" plotting.");
  
  pt++;
  c_pt++;

}

